﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XCSerialPort
{
    public class YedgeHelp
    {
        public Msg YedeHelp(decimal[] shoot_x_node, decimal[] shoot_y_node)
        {
            Msg ms = new Msg();
            ms.MsgState = true;
            if ((shoot_x_node[0] > shoot_x_node[1]) || (shoot_x_node[1] > shoot_x_node[2]) || (shoot_x_node[2] > shoot_x_node[3]))
            {
                ms.EerrorMsg = "检查：x值按照小到大递增排序";
                ms.MsgState = false;
            }

            var shoot_y_slope_lf = Math.Round((shoot_y_node[1] - shoot_y_node[0]) * 256.0m / (shoot_x_node[1] - shoot_x_node[0]));
            var shoot_y_slope_rt = Math.Round((shoot_y_node[1] - shoot_y_node[2]) * 256.0m / (shoot_x_node[3] - shoot_x_node[2]));

            var shoot_y_slope = new decimal[] { shoot_y_slope_lf, shoot_y_slope_rt };
            if (0 >= shoot_y_slope_lf || shoot_y_slope_lf > 8192)
            {
                ms.EerrorMsg = "检查：0 大于等于 (y2-y1)*256 / x2-x1 小于 0x2000";
                ms.MsgState = false;
            }
            if (0 >= shoot_y_slope_rt || shoot_y_slope_rt > 8192)
            {
                ms.EerrorMsg = "检查：0 大于等于 (y2-y3)*256 / x4-x3 小于 0x2000";
                ms.MsgState = false;
            }
            //decimal[] scale_dif = new decimal[256];
            //decimal tmp = 0;
            //for (int i = 0; i < scale_dif.Length; i++)
            //{
            //    if (i < shoot_x_node[0])
            //    {
            //        tmp = shoot_y_node[0];
            //    }
            //    else if (i < shoot_x_node[1])
            //    {
            //        tmp = shoot_y_slope_lf * (i - shoot_x_node[0]);
            //        tmp = ((int)tmp + 128) >> 8;
            //        tmp = tmp + shoot_y_node[0];
            //    }
            //    else if (i < shoot_x_node[2])
            //    {
            //        tmp = shoot_y_node[1];
            //    }
            //    else if (i < shoot_x_node[3])
            //    {
            //        tmp = shoot_y_slope_rt * (shoot_x_node[3] - i);
            //        tmp = ((int)tmp + 128) >> 8;
            //        tmp = tmp + shoot_y_node[2];
            //    }
            //    else {
            //        tmp = shoot_y_node[2];
            //    }
            //    scale_dif[i] = tmp;
            //}
            StringBuilder sb = new StringBuilder();
            sb.Append("// y_edge\n");
            sb.Append("0xfffd, 0x80,\n");
            sb.Append("0xfffe, 0x30,\n");
            sb.Append(para_to_reg(shoot_x_node, 8, "361d"));
            sb.Append(para_to_reg(shoot_y_node, 8, "3621"));
            sb.Append(para_to_reg(shoot_y_slope, 13, "3624"));

            ms.EerrorMsg = sb.ToString();
            return ms;
        }

        public List<ISPReg> para_to_reg(decimal[] para, int bits, string start_address)
        {
            List<ISPReg> list = new List<ISPReg>();
            try
            {

                var s_address = Convert.ToInt32(start_address, 16);
                for (int i = 0; i < para.Length; i++)
                {
                    var value_all = para[i];
                    var reg_num = Math.Ceiling((bits / 8.0));
                    for (int j = 0; j < reg_num; j++)
                    {
                        var tmp0 = s_address + (i + 1) * reg_num - (j + 1);
                        var tmp1 = ((int)tmp0).ToString("X2").PadLeft(4, '0');
                        var tmp2 = (((int)value_all) & 0xff).ToString("X2").PadLeft(2, '0');

                        list.Add(new ISPReg() { addr = Convert.ToUInt32(tmp1, 16), value = Convert.ToUInt32(tmp2, 16) });
                        value_all = (int)value_all >> 8;

                    }
                }
            }
            catch (Exception)
            {
                return null;
            }
            return list;
        }

        /// <summary>
        /// 备用nr3d 生产待测试
        /// </summary>
        /// <param name="para"></param>
        /// <param name="bits"></param>
        /// <param name="start_address"></param>
        /// <param name="ps0"></param>
        /// <param name="ps1"></param>
        /// <returns></returns>
        public List<ISPReg> para_to_reg(decimal[] para, int bits, string start_address, string ps0 = "", string ps1 = "")
        {
            List<ISPReg> list = new List<ISPReg>();
            try
            {
                var s_address = Convert.ToInt32(start_address, 16);

                var reg_num = Math.Ceiling((bits / 8.0));

                for (int i = 0; i < para.Length; i++)
                {
                    var value_all = para[i];
                    if (value_all < 0)
                    {
                        value_all = (1 << bits) + value_all;
                    }
                    for (int j = 0; j < reg_num; j++)
                    {
                        var tmp0 = s_address + (i + 1) * reg_num - (j + 1);
                        var tmp1 = ((int)tmp0).ToString("X2").PadLeft(4, '0');
                        var tmp2 = (((int)value_all) & 0xff).ToString("X2").PadLeft(2, '0');

                        list.Add(new ISPReg() { addr = Convert.ToUInt32(tmp1, 16), value = Convert.ToUInt32(tmp2, 16) });
                        value_all = (int)value_all >> 8;
                    }
                }



            }
            catch (Exception)
            {
                return null;
            }
            return list;
        }




        public void noise_profile(decimal[] x_node, decimal[] y_node, out decimal[] y_nos, out decimal[] slope)
        {
            var x_node_lf = x_node[0];
            var x_node_rt = x_node[1];
            var y_offset_lf = y_node[0];
            var y_limit_up = y_node[1];
            var y_offset_rt = y_node[2];

            var slope_lf = (y_limit_up - y_offset_lf) / (x_node_lf - 0);
            var slope_rt = (y_limit_up - y_offset_rt) / (255 - x_node_rt);
            slope_lf = Math.Round(slope_lf);
            slope_rt = Math.Round(slope_rt);
            slope = new decimal[] { slope_lf, slope_rt };
            var x_lit = new int[256];
            for (int i = 0; i < x_lit.Length; i++)
            {
                x_lit[i] = i;
            }
            var y_nos0 = new decimal[256];
            for (int i = 0; i < x_lit.Length; i++)
            {
                y_nos0[i] = (x_lit[i] * slope_lf + y_offset_lf);
            }
            var y_nos1 = new decimal[256];
            for (int i = 0; i < x_lit.Length; i++)
            {
                y_nos1[i] = ((255 - x_lit[i]) * slope_lf + y_offset_rt);
            }
            y_nos = new decimal[256];
            for (int i = 0; i < y_nos0.Length; i++)
            {
                y_nos[i] = Math.Min(y_nos0[i], y_nos1[i]);
            }
            for (int i = 0; i < y_nos.Length; i++)
            {
                y_nos[i] = Math.Min(y_nos[i], y_limit_up);
            }

        }


        public Msg y_enhance_paras(decimal Q_K, decimal K_r, decimal Y_r1, decimal Y_r2)
        {
            Msg ms = new Msg();
            ms.MsgState = true;
            if (Math.Abs(Y_r1 - Y_r2) > 128)
            {
                ms.EerrorMsg = "检查：R1-R2值小于于128";
                ms.MsgState = false;
            }
            if (K_r > ((int)K_r << (int)Q_K))
            {
                ms.EerrorMsg = "检查：K_r < (K_r>>Q_K)";
                ms.MsgState = false;
            }

            var gap = Y_r2 - Y_r1;
            if ((16 >= gap) && (gap >= 127))
            {
                ms.EerrorMsg = "检查：(16<=(R2-R1)) && ((R2-R1)<=127)";
                ms.MsgState = false;
            }
            var QKBase = (1 << (int)Q_K);
            var tmp = (QKBase * (double)gap / (double)K_r);
            tmp = Math.Log(tmp) / Math.Log(2.0);
            var Q_r1 = Math.Ceiling(tmp + 6);
            if (K_r == 0)
            {
                Q_r1 = 20;
            }
            else
            {
                if (Q_r1 > 20)
                {
                    Q_r1 = 20;
                }
                if (Q_r1 < 7)
                {
                    Q_r1 = 7;
                }
            }

            var Y_m1 = ((int)K_r << ((int)Q_r1 - (int)Q_K)) / gap;
            var Y_s1 = Q_r1 - (double)Q_K;
            if (Y_m1 > 128)
            {
                ms.EerrorMsg = "检查：Y_m1 > 128";
                ms.MsgState = false;
            }

            var estimation_error = ((int)((Y_r2 - Y_r1) * (int)Y_m1) >> (int)Y_s1) - K_r;
            if (estimation_error > 2)
            {
                ms.EerrorMsg = "检查：estimation_error > 2";
                ms.MsgState = false;
            }

            //List<ISPReg> regList = new List<ISPReg>();
            //regList.Add(new ISPReg() { addr = Convert.ToUInt32("fffd", 16), value = Convert.ToUInt32("80", 16) });
            //regList.Add(new ISPReg() { addr = Convert.ToUInt32("fffe", 16), value = Convert.ToUInt32("30", 16) });
            //regList.AddRange(para_to_reg(new decimal[1] { (int)Y_m1 }, 7, "4318"));
            //regList.AddRange(para_to_reg(new decimal[1] { (decimal)Y_s1 }, 4, "4319"));
            //ms.data = regList;
            List<decimal> _data = new List<decimal>();
            _data.Add((decimal)Y_m1);
            _data.Add((decimal)Y_s1);
            ms.data = _data;
            return ms;
        }


        public Msg c_enhance_paras(decimal trans_width)
        {
            Msg ms = new Msg();
            ms.MsgState = true;
            var Q_rc = Math.Ceiling(Math.Log((double)trans_width) / (double)Math.Log(2.0) + 4);
            if ((6 <= Q_rc) && (Q_rc <= 9))
            {
                ms.EerrorMsg = "检查：R1-R2值小于于128";
                ms.MsgState = false;
            }
            var trans_slope = (1 >> (int)Q_rc) / trans_width;

            //List<ISPReg> regList = new List<ISPReg>();
            //regList.Add(new ISPReg() { addr = Convert.ToUInt32("fffd", 16), value = Convert.ToUInt32("80", 16) });
            //regList.Add(new ISPReg() { addr = Convert.ToUInt32("fffe", 16), value = Convert.ToUInt32("30", 16) });
            //regList.AddRange(para_to_reg(new decimal[1] { (int)Q_rc }, 5, "4318"));
            //regList.AddRange(para_to_reg(new decimal[1] { (decimal)trans_slope }, 4, "4319"));
            List<decimal> _data = new List<decimal>();
            _data.Add((decimal)Q_rc);
            _data.Add((decimal)trans_slope);
            ms.data = _data;
            return ms;
        }

    }



    public class Msg
    {
        public string EerrorMsg;
        public bool MsgState;
        public List<decimal> data;
    }
}
